﻿using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Drawing.Processing;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using System.IO;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace NIDViewer
{
    public static class ImageTool
    {
        /// <summary>
        /// 生成颜色图
        /// </summary>
        /// <param name="datas"></param>
        /// <param name="points"></param>
        /// <param name="lines"></param>
        public static BitmapSource GeneratePicture(List<double> datas, int points, int lines, int width = 0, int height = 0)
        {
            // 加载色卡图片  
            var path = $"{AppDomain.CurrentDomain.BaseDirectory}Image\\ColourAtlas\\colourAtla.jpg";
            using Image<Rgba32> colorPaletteImage = SixLabors.ImageSharp.Image.Load<Rgba32>(path);
            int colorCount = colorPaletteImage.Width;

            var maxData = datas.Max() * 1E9;
            var minData = datas.Min() * 1E9;
            var Region = (maxData - minData);
            using Image<Rgba32> image = new(points, lines);
            for (int y = 0; y < lines; y++)
            {
                for (int x = 0; x < points; x++)
                {
                    int index = y * points + x; // 计算一维索引  
                    double value = datas[index] * 1E9;

                    var proportion = (value - minData) / Region;
                    proportion = Math.Clamp(proportion, 0, 1);
                    // 根据比例选择色卡中的颜色索引  
                    int colorIndex = (int)(proportion * (colorCount - 1));
                    var color = colorPaletteImage[colorIndex, 0]; // 从色卡中获取颜色  
                    // 设置对应像素的颜色  
                    image[x, lines - 1 - y] = color;
                }
            }
            if (width != 0 && height != 0)
                image.Mutate(ctx => ctx.Resize(width, height));
            return ImageToBitmapSource(image);
        }

        /// <summary>
        /// 生成灰度图
        /// </summary>
        /// <param name="datas"></param>
        /// <param name="points"></param>
        /// <param name="lines"></param>
        public static BitmapSource GenerateGrayPicture(List<double> datas, int points, int lines)
        {
            if (datas.Count > 0)
            {
                var maxData = datas.Max() * 1E9;
                var minData = datas.Min() * 1E9;
                var Region = (maxData - minData);
                using Image<Rgba32> image = new(points, lines);
                for (int y = 0; y < lines; y++)
                {
                    for (int x = 0; x < points; x++)
                    {
                        int index = y * points + x;
                        double value = datas[index] * 1E9;
                        // 将值限制在0和1之间  
                        var proportion = (value - minData) / Region;
                        proportion = Math.Clamp(proportion, 0, 1);
                        byte grayValue = (byte)(proportion * 255);
                        // 设置灰度值  
                        image[x, lines - 1 - y] = new Rgba32(grayValue, grayValue, grayValue, 255);
                    }
                }
                return ImageToBitmapSource(image);
            }
            return null;
        }

        public static BitmapSource ByteArrayToBitmapSource(byte[] byteArray)
        {
            // 创建一个内存流  
            using MemoryStream stream = new(byteArray);
            // 创建一个 BitmapSource  
            BitmapImage bitmap = new();
            bitmap.BeginInit();
            bitmap.StreamSource = stream;
            bitmap.CacheOption = BitmapCacheOption.OnLoad;
            bitmap.EndInit();
            bitmap.Freeze(); // 优化性能  
            return bitmap;
        }

        public static ImageSource? ConvertToImageSource(string base64String)
        {
            if (!string.IsNullOrWhiteSpace(base64String))
            {
                try
                {
                    // 移除可能的前缀  
                    if (base64String.Contains(','))
                    {
                        base64String = base64String.Split(',')[1];
                    }
                    // 解码Base64  
                    byte[] imageBytes = Convert.FromBase64String(base64String);
                    // 创建MemoryStream  
                    using var ms = new MemoryStream(imageBytes);
                    var bitmap = new BitmapImage();
                    bitmap.BeginInit();
                    bitmap.CacheOption = BitmapCacheOption.OnLoad;
                    bitmap.StreamSource = ms;
                    bitmap.EndInit();
                    bitmap.Freeze(); // 线程安全  
                    return bitmap;
                }
                catch
                {
                    return null;
                }
            }
            return null;
        }

        public static BitmapSource ListToBitmapSource(List<byte> byteArray)
        {
            // 创建一个内存流  
            using MemoryStream stream = new(byteArray.ToArray());
            // 创建一个 BitmapSource  
            BitmapImage bitmap = new();
            bitmap.BeginInit();
            bitmap.StreamSource = stream;
            bitmap.CacheOption = BitmapCacheOption.OnLoad;
            bitmap.EndInit();
            bitmap.Freeze(); // 优化性能  
            return bitmap;
        }

        /// <summary>
        /// 生成曲线图
        /// </summary>
        /// <returns></returns>
        public static BitmapSource GenerateGraph(int imageWidth, int imageHeight, List<SixLabors.ImageSharp.Point> points)
        {
            using var image = new Image<Rgba32>(imageWidth, imageHeight);

            // 填充背景  
            image.Mutate(ctx => ctx.Fill(SixLabors.ImageSharp.Color.White));

            var brush = SixLabors.ImageSharp.Drawing.Processing.Brushes.Solid(SixLabors.ImageSharp.Color.Black);
            var options = new DrawingOptions();
            for (int i = 0; i < points.Count - 1; i++)
            {
                image.Mutate(ctx => ctx.DrawLine(options, brush, 2, points[i], points[i + 1]));
            }
            return ImageToBitmapSource(image);
        }

        /// <summary>
        /// 生成曲线图
        /// </summary>
        /// <returns></returns>
        public static BitmapSource GenerateGraph(int imageWidth, int imageHeight, List<double> datas)
        {
            var stepX = 1.0f * imageWidth / datas.Count;
            var maxHeight = datas.Max() * 1E6;
            var minHeight = datas.Min() * 1E6;
            var minHeightAbs = minHeight > 0 ? -datas.Min() : Math.Abs(datas.Min());
            var stepY = imageHeight / Math.Abs(maxHeight - minHeight);

            var points = new List<PointF>();
            var x = 1;
            foreach (var y in datas)
            {
                points.Add(new PointF(x * stepX, (float)(imageHeight - (y + minHeightAbs) * 1E6 * stepY)));
                x++;
            }

            //绘图
            using var image = new Image<Rgba32>(imageWidth, imageHeight);
            image.Mutate(ctx => ctx.Fill(SixLabors.ImageSharp.Color.White));
            var brush = SixLabors.ImageSharp.Drawing.Processing.Brushes.Solid(SixLabors.ImageSharp.Color.Black);
            var options = new DrawingOptions();
            for (int i = 0; i < points.Count - 1; i++)
            {
                image.Mutate(ctx => ctx.DrawLine(options, brush, 2, points[i], points[i + 1]));
            }
            return ImageToBitmapSource(image);
        }

        private static BitmapSource ImageToBitmapSource(Image<Rgba32> img)
        {
            using MemoryStream memoryStream = new();
            img.SaveAsPng(memoryStream); // 保存为 PNG 格式  
            memoryStream.Seek(0, SeekOrigin.Begin);

            // 创建 BitmapImage  
            BitmapImage bitmapImage = new();
            bitmapImage.BeginInit();
            bitmapImage.StreamSource = memoryStream;
            bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
            bitmapImage.EndInit();
            bitmapImage.Freeze();

            return bitmapImage;
        }

        private static List<double> DownSample(List<double> datas, int maxPoints)
        {
            if (datas.Count <= maxPoints) return datas;

            var step = (int)Math.Ceiling((double)datas.Count / maxPoints);
            var result = new List<double>();

            for (int i = 0; i < datas.Count; i += step)
            {
                result.Add(datas[i]);
            }
            return result;
        }

        public static byte[] BitmapSourceToByteArray(BitmapSource bitmapSource)
        {
            // 使用PngBitmapEncoder将BitmapSource编码为PNG格式
            var encoder = new PngBitmapEncoder();
            encoder.Frames.Add(BitmapFrame.Create(bitmapSource));

            using (MemoryStream stream = new MemoryStream())
            {
                encoder.Save(stream);
                return stream.ToArray();
            }
        }
    }
}
